home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Computer Select (Limited Edition)
/
Computer Select.iso
/
pcmag
/
v11n07
/
dosclip.asm
< prev
next >
Wrap
Assembly Source File
|
1992-04-03
|
69KB
|
1,973 lines
page 66,132
;============================================================================
; DOSCLIP.COM impliments a DOS clipboard
;
; Usage: DOSCLIP [/B][/U]
;
; B = Use Video BIOS calls
; U = Uninstall
;
; Revision History:
;
; Version 1.0 Initial Release
;
;============================================================================
POPTIME equ 9 ;Allow 1/2 second to popup
COPYTIME equ 180 ;Allow 10 seconds to copy
STACKSIZE equ 512 ;TSR stack
INSTDATASIZE equ offset DataBlockEnd - offset DataBlock
MSGBOX_BUFFSIZE equ 1 * 132 * 2 ;Screen save buff for title
HELPBOX_BUFFSIZE equ 5 * 132 * 2 ;Screen save buff for help
RES_STACK equ offset end_of_resident + STACKSIZE
MSGBOX_BUFFER equ offset end_of_resident + STACKSIZE
ATTR_BUFFER equ MSGBOX_BUFFER + MSGBOX_BUFFSIZE
;----------------------------------------------------------------------------
; BIOS Data segment
;----------------------------------------------------------------------------
bios_data segment at 40h
org 17h
shift_state db ? ;State of keyboard shift keys
org 1Ah
keybuff_head dw ? ;Start ptr for keyboard buff
keybuff_tail dw ? ;End ptr for keyboard buff
org 4Eh
video_buffoff dw ? ;Offset of video buffer
org 63h
video_ioregs dw ? ;I/O addr of video controller
org 80h
keybuff_start dw ? ;Start ptr for keyboard buff
keybuff_end dw ? ;End ptr for keyboard buff
video_rows db ? ;Number of rows on the screen
bios_data ends
;----------------------------------------------------------------------------
; DOSCLIP Code and Data segments
;----------------------------------------------------------------------------
code segment
assume cs:code
org 2ch
env_segment dw ? ;Word containing the segment
; of the program's env. block.
org 80h
command_tail db ? ;Offset of the command tail.
org 100h
prog: jmp initialize
;--------------------------------------------------------------------------- pushf
; Resident Data (Global to all sessions)
;--------------------------------------------------------------------------- pushf
program db 13,10
program1 db "DOSCLIP 1.0 "
copyright db "(c) 1992 Douglas Boling"
program2 db 10,13
db "First published in PC Magazine, April 14, 1992"
db 13,10,"$",1Ah
def_marked_bw db 70h ;Default marked attr B/W
def_text_bw db 70h ;Default text attr B/W
bw_segment dw 0B000h ;Segment of B/W video memory
def_marked_clr db 70h ;Default marked attr Color
def_text_clr db 71h ;Default text attr Color
clr_segment dw 0B800h ;Segment of color video memory
attr_buffsize dw 1024 ;Size of attribute buffer
helpbox_buff dw 0 ;Pointer to helpbox buffer
copykey db 2eh ;Hotkey for copy command 'C'
copyshift db 08h ;Shift for copy hotkey. 'Alt'
pastekey db 2Fh ;Hotkey for paste command 'V'
pasteshift db 08h ;Shift for paste hotkey. 'Alt'
clipboard_buff dd 0 ;Pointer to clipboard buffer
clipboard_size dw 4096 ;Max size of clipboard
clipboard_dptr dd 0 ;Ptr data in clipboard
clipboard_dsize dw 0 ;Size of data in clipboard
win_enhanced db 0 ;Enhanced mode Windows active
indos_ptr dd -1 ;Pointer to INDOS flag
criterr_ptr dd -1 ;Pointer to DOS crit err flag
int08h dd -1 ;Int 08 vector (Timer)
int09h dd -1 ;Int 09 vector (Keyboard HW)
int10h dd -1 ;Int 10 vector (Video BIOS)
int13h dd -1 ;Int 13 vector (Disk BIOS)
int16h dd -1 ;Int 16 vector (Keyboard)
int28h dd -1 ;Int 28 vector (DOS Idle)
int2Fh dd -1 ;Int 2F vector (DOS Multiplex)
keycodes db 3bh,51h,49h,4fh,47h,48h,50h,74h,73h,4bh,4dh
keycodes_end = $
keyjmp_table dw offset cursor_rt ;Index into key routines are
dw offset cursor_lt ; inverse of order of
dw offset cursor_clt ; keycode array.
dw offset cursor_crt
dw offset cursor_dn
dw offset cursor_up
dw offset cursor_home ;Home
dw offset cursor_end ;End
dw offset cursor_top ;Page Up
dw offset cursor_bottom ;Page Down
dw offset showhelp ;F1
helptag db "F1 for Help "
helptag_end = $
db 0 ;Terminating 0 for helptag
no_help db 0 ;Blocks help msg
; 1234567891123456789212345678931234567894
helpmsg1 db " <Cursor> keys delete box/move cursor "
db " <Shift><Cursor> keys size box",0
helpmsg2 db " <Home> Move to start of line "
db " <End> Move to end of line",0
helpmsg3 db " <Pg Up> Move to top of screen "
db " <Pg Dn> Move to bot of screen",0
helpmsg4 db " <C> Copy box into clipboard "
db " <V> Paste clipboard data",0
helpmsg5 db " <Esc> Exit the program",0
;
;Screen variables
;
BIOSFlag db 0 ;1 = Use Vid BIOS calls
video_ptr label dword
video_offset dw 0 ;Offset of video memory
video_seg dw 0 ;Segment of video memory
;
;Switcher global data structures
;
StartupInfo = $
sisVersion dw 3 ;Switcher structure ID
sisNextDev dd 0 ;Ptr to prev startup structure
sisVirtDevFile dd 0 ;Ptr to name of opt dev drvr
sisReferenceData dd 0 ;Data for Win dev drivr
sisInstData dd 0 ;Ptr to instance mem list
DataBlockPtr dd 0 ;Ptr to instance data
DataBlockSize dw 0 ;Size of instance data
StackBlockPtr dd 0 ;Ptr to instance stack
StackBlockSize dw 0 ;Size of instance stack
dd 0 ;Ptr to next block = 0 to
dw 0 ; terminate list
;============================================================================
;Instance data
;============================================================================
DataBlock = $
;
; Program Instance data
;
hotshift db 0ah ;Shift condition for popup
popflag db 0 ;Go active counter
int08_active db 0 ;Interrupt active flag
int09_active db 0 ;Interrupt active flag
int10_active db 0 ;Interrupt active flag
int13_active db 0 ;Interrupt active flag
int28_active db 0 ;Interrupt active flag
int2F_active db 0 ;Interrupt active flag
main_active db 0 ;TSR active flag
saved_ss dw 0 ;Saved forground stack ptr
saved_sp dw 0
copy_flag db 0 ;Flag indicating copy to clip
paste_flag db 0 ;Flag indicating paste
marked_attr db 0 ;Screen attr for marked area
text_attr db 0 ;Attribute for msg box text
cursor_pos dw 0 ;Cursor position at popup
cursor_type dw 0 ;Cursor shape at popup
screen_page db 0 ;Active video page
screen_size label word
screen_cx db 0 ;Screen columns
screen_cy db 0 ;Screen rows
marked_pos1 label word
marked_x1 db 0 ;Marked area starting column
marked_y1 db 0 ;marked area starting row
marked_pos2 label word
marked_x2 db 0 ;Marked area ending column
marked_y2 db 0 ;marked area ending row
oldmarked_pos1 label word
oldmarked_x1 db 0 ;Marked area starting row
oldmarked_y1 db 0 ;marked area starting column
oldmarked_pos2 label word
oldmarked_x2 db 0 ;Marked area columns
oldmarked_y2 db 0 ;marked area rows
boxactive db 0 ;Flag for message box
DataBlockEnd = $
;============================================================================
; VIDEOINT processes BIOS video services interrupt (Int 10h)
;============================================================================
videoint proc far
assume cs:code,ds:nothing,es:nothing
inc cs:int10_active
pushf
call cs:[int10h] ;Call old int
dec cs:int10_active
iret ;Return
videoint endp
;============================================================================
; DISKINT processes BIOS disk services interrupt (Int 13h)
;============================================================================
diskint proc far
assume cs:code,ds:nothing,es:nothing
inc cs:int13_active
pushf
call cs:[int13h] ;Call old int
pushf
dec cs:int13_active
popf
ret 2 ;Return preserving flags
diskint endp
;============================================================================
; TIMERINT processes timer interrupt (Int 08h)
;============================================================================
timerint proc far
assume cs:code,ds:nothing,es:nothing
pushf
call cs:[int08h] ;Call old int 8
push ax
push ds
mov ax,cs
mov ds,ax
assume ds:code
cmp int08_active,0 ;See if we are in this
jne timerint_exit1 ; routine already
inc int08_active ;Set int active flag
cmp popflag,0 ;See if we need to try to
jne timer_check ; pop up
cmp paste_flag,1 ;See if there is data to
je timer_paste_2 ; paste from clipboard
ja timer_paste
timerint_exit:
dec int08_active ;Clear int active flag
timerint_exit1:
pop ds
pop ax
iret ;Return
timer_check:
call check_system ;See if system OK to pop up
or ax,ax
jne timerint_dec
call main ;Call the TSR
mov popflag,1
timerint_dec:
dec popflag
jmp short timerint_exit
timer_paste_2:
cmp paste_flag,1 ;See if there is data to
jne timerint_exit ; paste
call push_key
jnc timer_paste_2
jmp short timerint_exit
timer_paste:
cmp win_enhanced,0 ;See if Win/386 active
je timer_paste_1
call getwinclip ;Get data from the clipboard
cmp ax,-1 ;If -1, can't open clipboard,
je timerint_exit ; try again later.
mov paste_flag,0 ;If 0, no data available.
or ax,ax
je timerint_exit
mov clipboard_dsize,ax ;Else, AX = bytes
mov ax,word ptr clipboard_buff ; read from CB.
mov word ptr clipboard_dptr,ax
mov paste_flag,1
jmp short timer_paste_2
timer_paste_1:
mov paste_flag,0 ;If no Win/386, see if any
cmp clipboard_dsize,0 ; data in the clipboard.
je timerint_exit ; If not, cancel paste.
mov paste_flag,1
jmp short timer_paste_2
timerint endp
;============================================================================
; KEYINT processes keyboard interrupts (Int 09h)
;============================================================================
keyint proc far
assume cs:code,ds:nothing,es:nothing
push ax
push ds
mov ax,40h
mov ds,ax ;Set ES to bios data segment
assume ds:bios_data
mov ah,ds:[shift_state]
and ah,0fh ;Mask lock bits
cmp ah,cs:[copyshift]
je keyint_copy
keyint_1:
cmp ah,cs:[pasteshift]
je keyint_paste
keyint_jmp:
pop ds
pop ax
jmp cs:[int09h] ;Call old int 9
keyint_exit:
cli ;Disable interrupts
in al,61h ;Reset the keyboard
mov ah,al ; controller
or al,80h
out 61h,al
mov al,ah
out 61h,al
mov al,20h ;Signal end-of-interrupt to
out 20h,al ; the interrupt controller
sti ;Enable interrupts
pop ds
pop ax
iret
keyint_copy:
in al,60h ;Get scan code from keyboard
cmp al,cs:copykey
jne keyint_1
mov cs:popflag,POPTIME ;Set timer to pop up
jmp short keyint_exit
keyint_paste:
in al,60h ;Get scan code from keyboard
cmp al,cs:pastekey ;Compare to paste hotkey
jne keyint_jmp
mov cs:paste_flag,2 ;Set Paste flag
jmp short keyint_exit
keyint endp
;============================================================================
; IDLEINT processes DOS Idle interrupt (Int 28h)
;============================================================================
idleint proc far
assume cs:code,ds:nothing,es:nothing
pushf
call cs:[int28h] ;Call old int
push ds
push cs
pop ds
assume ds:code
cmp int28_active,0 ;See if we are in this
jne idleint_exit1 ; routine already
inc int28_active ;Set int active flag
cmp popflag,0 ;See if we need to try to
jne idle_check ; pop up
idleint_exit:
dec int28_active ;Clear int active flag
idleint_exit1:
pop ds
iret ;Return
idle_check:
push ax
call check_system ;See if OK to pop up. Ignore
or al,al ; INDOS since in idle.
jne idleint_1
mov popflag,0 ;Clear popup flag
call main ;Call the TSR
idleint_1:
pop ax
jmp short idleint_exit
idleint endp
;============================================================================
; MUXINT processes DOS multiplex interrupt (Int 2Fh)
;============================================================================
muxint proc far
assume cs:code,ds:nothing,es:nothing
cmp ax,1605h ;See if Windows launch
je mux_winstart
cmp ax,1606h ;See if Windows terminate
je mux_winend
cmp ax,1608h ;See if Windows launch
je mux_wingo ; complete
cmp ax,4b05h ;See if switcher get instance
je init_instance ; data.
muxint_jmp:
jmp cs:[int2Fh] ;Jump to old int
mux_winend:
test dx,01h ;See if enhanced mode Windows
jne muxint_jmp
dec cs:win_enhanced ;Clear Enhanced mode win flag
jmp short muxint_jmp
mux_wingo:
cmp cs:clipboard_dsize,0 ;If Windows starts and we
je muxint_jmp ; have data in our
cmp cs:win_enhanced,0 ; clipboard, copy our
je muxint_jmp ; data to the Win clipboard
mov cs:copy_flag,COPYTIME
jmp short muxint_jmp
mux_winstart:
test dx,01h ;See if enhanced mode Windows
jne init_instance
inc cs:win_enhanced
init_instance:
pushf
call cs:[int2fh] ;Call old int
mov word ptr cs:[sisNextDev],bx
mov word ptr cs:[sisNextDev+2],es
push cs ;ES:BX point to switcher struc
pop es
mov bx,offset StartupInfo
jmp short muxint_exit
muxint_exit:
iret
muxint endp
;--------------------------------------------------------------------------- pushf
; Check System Determines if the system is in a state compatible with TSRs
; Exit: AL - ORed flags for DOS Idle OK
; AH - State of INDOS flag
;--------------------------------------------------------------------------- pushf
check_system proc near
assume cs:code,ds:code,es:nothing
push bx
push ds
xor ax,ax
or al,int10_active ;Check BIOS video int
or al,int13_active ;Check BIOS disk int
lds bx,criterr_ptr ;Check DOS critical error
or al,byte ptr ds:[bx] ; flag.
lds bx,cs:indos_ptr ;Check INDOS flag
mov ah,byte ptr ds:[bx]
check_sys_exit:
pop ds
pop bx
ret
check_system endp
;-----------------------------------------------------------------------------
; GETWINCLIP Gets any data from the Windows Clipboard
; Exit AX - FF Can't open clipboard
; 0 Error in clipboard or clipboard data not available
; Else, number of bytes read from clipboard
;-----------------------------------------------------------------------------
getwinclip proc near
assume ds:code
mov ax,1701h ;Open Clipboard
int 2fh
or ax,ax ;Error opening, exit
mov ax,-1
je getwinclip_exit1
push bx
push dx
push es
mov ax,1704h ;Get clipboard data size
mov dx,7 ;Request OEM Text
int 2fh
or dx,dx ;See if too much data
jne getwinclip_exit
cmp ax,clipboard_size
jbe getwinclip_1
xor ax,ax ;Indicate error
jmp short getwinclip_exit
getwinclip_1:
cmp dx,ax ;If 0 size, no data in
je getwinclip_exit ; correct format.
push ax
mov ax,1705h ;Get clipboard data
les bx,clipboard_buff
mov dx,7 ;Get OEM text
int 2fh
or ax,ax
pop ax
je getwinclip_exit
dec ax
getwinclip_exit:
push ax
mov ax,1708h ;Close Clipboard
int 2fh
pop ax
pop es
pop dx
pop bx
getwinclip_exit1:
ret
getwinclip endp
;-----------------------------------------------------------------------------
; GETCLIPSIZE Gets the size of the data in the Windows clipboard
;-----------------------------------------------------------------------------
getclipsize proc near
assume ds:code
mov ax,1701h ;Open Clipboard
int 2fh
or ax,ax ;Error opening, exit
je getclipsize_exit
mov ax,1704h ;Get clipboard data size
mov dx,7 ;Request OEM Text
int 2fh
mov ax,1708h ;Close Clipboard
int 2fh
pop es
pop dx
pop bx
getclipsize_exit:
ret
getclipsize endp
;-----------------------------------------------------------------------------
; SETWINCLIP Sets the Windows clipboard
; Exit: ZF - Set if error
;-----------------------------------------------------------------------------
setwinclip proc near
assume ds:code
push bx
push cx
push dx
push si
push es
mov ax,1700h ;Check API
int 2fh
or ax,ax ;no API
je setwinclip_exit1
mov ax,1701h ;Open Clipboard
int 2fh
or ax,ax ;Error opening, exit
je setwinclip_exit1
mov ax,1702h ;Clear Clipboard
int 2fh
or ax,ax ;Error, exit
je setwinclip_exit1
mov ax,1703h ;Set clipboard data
les bx,clipboard_buff ;ES:BX ptr to data
xor si,si ;SI,CX = data size
mov cx,clipboard_dsize
mov dx,7 ;Data format is OEM text
int 2fh
setwinclip_exit:
mov ax,1708h ;Close Clipboard
int 2fh
or ax,ax ;Set ZF if error
setwinclip_exit1:
pop es
pop si
pop dx
pop cx
pop bx
ret
setwinclip endp
;-----------------------------------------------------------------------------
; INCKEYPTR Incriments the keyboard buffer pointer
; Entry: DI - Current Keyboard tail pointer
;-----------------------------------------------------------------------------
inckeyptr proc near
assume ds:bios_data
inc di ;Make room in buffer
inc di
cmp di,ds:[keybuff_end] ;Get ptr to end of buffer
jne inckeyptr_1
mov di,ds:[keybuff_start] ;Get ptr to buffer offset
inckeyptr_1:
ret
inckeyptr endp
;-----------------------------------------------------------------------------
; PUSH KEY Fills the keyboard buffer with data from the clipboard.
; Exit: CF - Set if keyboard buffer full
; AX - modified
;-----------------------------------------------------------------------------
push_key proc near
assume ds:nothing,es:nothing
push di
push si
push ds
push es
cli
mov ax,bios_data
mov ds,ax
assume ds:bios_data
cli ;No interrupts
mov di,ds:[keybuff_tail]
push di
call inckeyptr
cmp di,ds:[keybuff_head] ;See if buffer full
pop di
stc
je push_key_exit
les si,cs:[clipboard_dptr] ;Get ptr to clip data
mov ax,word ptr cs:[clipboard_buff]
add ax,cs:[clipboard_dsize] ;Add size of data
cmp ax,si ;See if at end of buffer
mov al,es:[si] ;Get clipboard byte
jne push_key_2 ;No, continue
mov cs:[paste_flag],0 ;Clear paste flag
mov si,word ptr cs:[clipboard_buff] ;Reset data ptr
dec si
push_key_2:
or al,al ;Don't stuff null char
je push_key_3
cmp al,0ah ;Don't stuff line feeds
je push_key_3
xor ah,ah ;Clear scan code
cmp al,0dh ;If CR character, add proper
jne push_key_21 ; scan code for Word Perfect
mov ah,1ch
push_key_21:
mov ds:[di],ax ;Push data into keyboard buff
call inckeyptr
mov ds:[keybuff_tail],di ;Save keybuff ptr
push_key_3:
inc si ;Update clip data ptr
mov word ptr cs:[clipboard_dptr],si ;Save clipdata ptr
clc
push_key_exit:
sti ;Allow interrupts
pop es
pop ds
pop si
pop di
ret
push_key endp
;============================================================================
; MAIN This routine does most of the work for the TSR
;============================================================================
main proc near
assume cs:code,ds:code,es:nothing
cmp main_active,0 ;See if already active
jne main_exit
cli
inc main_active
mov [saved_sp],sp ;Save old stack pointer
mov [saved_ss],ss
mov ax,cs ;Set ss:sp to internal stack
mov ss,ax
mov sp,RES_STACK
sti ;Enable interrupts
cld ;Set string direction UP
push bx
push cx
push dx
push di
push si
push bp
push es
mov ah,0fh ;Get display mode
int 10h
cmp al,7
je main_1 ;Pop up only if in text mode.
cmp al,4
jb main_1
main_exit1:
pop es
pop bp
pop si
pop di
pop dx
pop cx
pop bx
cli
mov ss,[saved_ss] ;Restore old stack
mov sp,[saved_sp]
dec main_active
main_exit:
ret
main_1:
xor dl,dl
mov no_help,dl ;Enable help message
mov copy_flag,dl ;Clear copy to clip flag
cmp ah,80
jb main_exit1
mov screen_page,bh ;Save active video page
mov screen_cx,ah ;Save screen columns
mov ah,3 ;Get cursor position
int 10h
mov cursor_pos,dx ;Save cursor information
mov cursor_type,cx
cmp dh,0 ;If on top line, move down 1
jne main_11 ; to miss banner.
inc dh
main_11:
mov marked_pos1,dx ;Save initial cursor position
mov ax,40h
mov es,ax ;Set ES to bios data segment
assume es:bios_data
mov ah,12h ;Determine if CGA by checking
mov bl,10h ; for EGA compatibility
int 10h
mov al,24 ;CGA, only 25 rows on screen
cmp bl,10h
je main_2
mov al,es:video_rows ;Get number of rows on screen
main_2:
mov screen_cy,al ;Save screen rows
mov ax,es:video_buffoff ;Copy ptr to video memory
mov video_offset,ax
mov ax,marked_pos1 ;Copy starting pos to ending
mov marked_pos2,ax ; pos to zero block.
mov oldmarked_pos1,ax
mov oldmarked_pos2,ax
test es:video_ioregs,40h ;See if color or monochrome
jne main_colorvid
mov si,offset def_marked_bw ;Point to B/W parameters
jmp short main_3
main_colorvid:
mov si,offset def_marked_clr ;Point to color parameters
main_3:
push ds
pop es
assume es:code
mov di,offset marked_attr ;Copy default attributes
movsw
lodsw ;Get Video buffer segment
mov video_seg,ax
mov ah,1 ;Hide the cursor by changing
mov cx,200h ; the size of the cursor
int 10h
call init_attrlist ;Initialize attr save list
jc main_end1
mov dx,marked_pos1 ;Mark initial cursor where
call getchar ; the old cursor was
mov ah,marked_attr ;Mark cursor position on
call putchar ; screen.
main_loop:
cmp boxactive,1 ;If box active, don't reprint
je main_4 ; the box.
mov al,marked_y2 ;If cursor on top line, don't
or al,marked_y2 ; print the title box.
je main_4
call msgbox ;Draw title box
main_4:
call getkey ;Wait for a key
cmp al,27 ;If ESC, end.
je main_end
cmp ah,pastekey ;If 'v' paste and exit
je main_paste
cmp ah,28 ;If Enter, copy and exit
je main_copy
cmp ah,copykey ;If 'c' copy and exit
je main_copy
mov al,ah ;Copy scan code
main_6:
mov di,offset keycodes
mov cx,offset keycodes_end - offset keycodes
repne scasb
jne main_loop
shl cx,1 ;Convert key num into jump
mov bx,cx ; table index.
mov ax,marked_pos2 ;Preload parameters into regs
mov cx,screen_size ; to save code
call [keyjmp_table+bx] ;Call key routine
jmp short main_loop
main_copy:
mov copy_flag,1
jmp short main_end
main_paste:
cmp win_enhanced,0 ;If enhanced mode Windows
je main_paste_1 ; active, get clipboard
call getwinclip ; data from the Windows
jmp short main_end ; Clipboard.
main_paste_1:
cmp clipboard_dsize,0 ;If clipboard empty, don't
je main_end ; paste.
mov paste_flag,1
main_end:
call clearmarked ;Restore attributes
call clearbox ;Delete title box
main_end1:
mov ah,1 ;Set cursor type
mov cx,cursor_type
mov bh,screen_page
int 10h
mov ah,2 ;Set cursor position
mov dx,cursor_pos
int 10h
jmp main_exit1
main endp
;-----------------------------------------------------------------------------
; CURSOR KEYS Handles the actions of the cursor keys as the user uses them
; to mark the selected area.
; Entry: AL - marked_x2
; AH - marked_y2
; CL - screen_cx
; CH - screen_cy
;-----------------------------------------------------------------------------
cursor_keys proc near
; CURSOR HOME Moves the cursor to the left most column
cursor_home:
xor al,al ;Zero current column
jmp short cursor_1
; CURSOR END Moves the cursor to the right most column
cursor_end:
mov al,cl ;Set Cur column to screen cols
dec al
jmp short cursor_1
; CURSOR TOP Moves the cursor to the top row
cursor_top:
mov ah,1 ;Move to line 1 to avoid
jmp short cursor_1 ; title erase
; CURSOR END Moves the cursor to the bottom row
cursor_bottom:
mov ah,ch ;Set Cur Row to screen rows
jmp short cursor_1
; CURSOR UP Moves the marked orgin up one row
cursor_up:
or ah,ah
je cursor_1
dec ah
jmp short cursor_1
; CURSOR DN Moves the marked orgin down one row
cursor_dn:
cmp ah,ch
je cursor_1
inc ah
jmp short cursor_1
; CURSOR CLT Moves the marked orgin left 8 columns
cursor_clt:
sub al,8
jae cursor_1
xor al,al
jmp short cursor_1
; CURSOR CRT Moves the marked orgin right 8 columns
cursor_crt:
add al,8
dec cl
cmp al,cl
jb cursor_1
mov al,cl
jmp short cursor_1
; CURSOR LT Moves the marked orgin left one col
cursor_lt:
or al,al
je cursor_1
dec al
jmp short cursor_1
; CURSOR RT Moves the marked orgin right one col
cursor_rt:
dec cl
cmp al,cl
jae cursor_1
inc al
cursor_1:
mov marked_pos2,ax ;Save new position
push ax
mov ah,2 ;Get shift state
int 16h
and al,3
pop ax
jne cursor_2
mov marked_pos1,ax ;Not shifted, set points equal
cursor_2:
or ah,ah ;If cursor on top line, clear
jne cursor_3 ; title box so user can see
call clearbox ; what is on top line.
cursor_3:
call drawmarked
ret
cursor_keys endp
;-----------------------------------------------------------------------------
; DRAWMARKED Displays the marked area by changing the screen attributes
; inside the marked area.
;-----------------------------------------------------------------------------
drawmarked proc near
push es
mov ax,marked_pos1
mov dx,marked_pos2
cmp dx,oldmarked_pos2
jne drawmarked_1
cmp ax,oldmarked_pos1
je drawmarked_exit
drawmarked_1:
mov bx,offset marked_pos1
mov cx,4
drawmarked_2:
call find_min ;AX = upper left corner
call find_max ;DX = lower right corner
add bx,2
loop drawmarked_2
drawmarked_7:
sub dx,ax ;Compute size of area
xor cx,cx
mov cl,dl ;Copy column count
mov si,cx
inc si
mov cl,dh ;Copy row count
inc cx
mov dx,ax ;Copy starting row, column
drawmarked_8:
push cx ;Save row count
push dx ;Save cursor position
mov cx,si ;Get column count
drawmarked_9:
mov bx,offset marked_pos1
call chk_inwin
mov ah,al ;Save in marked area flag
mov bx,offset oldmarked_pos1
call chk_inwin
cmp ah,al ;See if in or out of both
je drawmarked_11 ; areas. If so, no change.
push ax ;Save in-window flags
call getchar
pop bx
or bh,bh ;See if in marked area
je drawmarked_10
mov ah,marked_attr ;Mark character
call putchar
jmp short drawmarked_11
drawmarked_10:
call get_attr ;Get saved screen attribute
call putchar ;Restore attribute
drawmarked_11:
inc dl
loop drawmarked_9
pop dx
pop cx
inc dh
loop drawmarked_8
mov ax,marked_pos1 ;Update old pointers
mov oldmarked_pos1,ax
mov ax,marked_pos2
mov oldmarked_pos2,ax
drawmarked_exit:
pop es
ret
drawmarked endp
;-----------------------------------------------------------------------------
; CLEARMARKED Restores the marked area to its original screen attributes
;-----------------------------------------------------------------------------
clearmarked proc near
assume ds:code
push es
mov bx,offset marked_pos1
call compute_box
sub ax,dx
xor cx,cx
mov cl,al
mov si,cx ;Save column count
inc si
mov cl,ah
inc cx
xor bx,bx
cmp copy_flag,0
je clearmarked_3
mov bx,clipboard_size
les di,clipboard_buff
mov word ptr [clipboard_dptr],di
clearmarked_3:
push cx
push dx
mov cx,si ;Get row count
clearmarked_4:
call getchar
or bx,bx ;If copying data to
je clearmarked_5 ; clipboard, save char.
stosb
dec bx
clearmarked_5:
call get_attr ;Get saved screen attribute
call putchar
inc dl
loop clearmarked_4
or bx,bx
je clearmarked_6
mov ax,0a0dh ;Append CR-LF to line
stosw
dec bx
dec bx
clearmarked_6:
pop dx
pop cx
inc dh
loop clearmarked_3
cmp copy_flag,0
je clearmarked_exit
xor al,al
stosb
dec bx
sub bx,clipboard_size
not bx
mov clipboard_dsize,bx
mov ax,word ptr cs:[clipboard_buff]
mov word ptr cs:[clipboard_dptr],ax
cmp win_enhanced,0 ;If enhanced mode Windows
je clearmarked_exit ; active, save data to
call setwinclip ; Windows clipboard
clearmarked_exit:
pop es
ret
clearmarked endp
;-----------------------------------------------------------------------------
; GET ATTR Gets a saved attribute in the attribute buffer for a given
; cursor location.
; Entry: DX - Row, Column of character
; Exit: AH - Attribute
;-----------------------------------------------------------------------------
get_attr proc near
push cx
push dx
push si
push ax
call compute_offset ;Get count into buffer
mov si,ATTR_BUFFER
xor ax,ax
mov dx,ax
get_attr_1:
lodsb ;Get count byte
inc si
or al,al
je get_attr_exit
sub cx,ax
jae get_attr_1
mov dh,[si-1] ;Get attribute
get_attr_exit:
pop ax
mov ah,dh ;Copy attribute
pop si
pop dx
pop cx
ret
get_attr endp
;-----------------------------------------------------------------------------
; INIT ATTRLIST Initializes the attribute list
;-----------------------------------------------------------------------------
init_attrlist proc near
assume ds:code
mov bx,screen_size ;Get size of screen
inc bh
inc bh
xor ax,ax
mov dx,ax ;Start at top left corner
mov cx,ax
xchg bh,cl ;CX-Col count, BX-Row cnt
mov si,bx
mov di,ATTR_BUFFER ;Get pointer to buffer
call getchar
mov bh,ah
mov bl,0
init_attrlist_1:
push cx
push dx
mov cx,si ;Get number of columns
init_attrlist_2:
call getchar ;Read attribute
cmp bh,ah ;Compare attributes
jne init_attrlist_newblk ;If different write block
inc bl ;Incriment count
cmp bl,-1 ;If count full, write block
je init_attrlist_newblk
mov bh,ah ;Copy attribute value
init_attrlist_3:
inc dl ;Next column
loop init_attrlist_2
pop dx
pop cx
inc dh ;Next row
loop init_attrlist_1
clc
init_attrlist_exit:
ret
init_attrlist_newblk:
mov ds:[di],bx ;Write old block to list
inc di ;Update ptr
inc di
mov bl,1 ;New count
mov bh,ah ;Copy new attribute
cmp di,helpbox_buff
jb init_attrlist_3 ;If list runs into the help
inc no_help ; buffer, disable help
push ax
mov ax,helpbox_buff ;If past helpbox buffer, exit
add ax,HELPBOX_BUFFSIZE
cmp di,ax
pop ax
jb init_attrlist_3 ;If list past help box
stc ; buffer, exit prog.
jmp short init_attrlist_exit
init_attrlist endp
;-----------------------------------------------------------------------------
; COMPUTE OFFSET Computes the offset into the attribute buffer for a
; given cursor location.
; Entry: DX - Row, Column of character
; Exit: CX - Offset in buffer.
;-----------------------------------------------------------------------------
compute_offset proc near
push ax
push dx
mov al,dh ;Copy column
mul screen_cx ;Mul by width of screen
xor dh,dh
add ax,dx ;Add row
xchg cx,ax
pop dx
pop ax
ret
compute_offset endp
;-----------------------------------------------------------------------------
; CHK INWIN Determines if a character is inside the bounds of an area
; Entry: BX - Pointer to bounding rectangle
; x1 db point 1 column
; y1 db point 1 row
; x2 db point 2 column
; y2 db point 2 row
; DX - Row, Column of character
; Exit: AL - <> 0 if inside area
;-----------------------------------------------------------------------------
chk_inwin proc near
push bx
push cx
push ax ;Save AX
push dx ;Save current cursor pos
call compute_box ;DX = UL corner, AX = LR corner
pop bx
xchg bx,dx ;DX = cur cursor, BX=UL corner
mov cx,ax ;CX = LR corner
pop ax ;Restore AX
mov al,0 ;Clear inbox flag
cmp dl,bl ;See if above starting row
jb chk_inwin_exit
cmp dh,bh ;See if left of starting col
jb chk_inwin_exit
cmp dl,cl ;See if below ending row
ja chk_inwin_exit
cmp dh,ch ;See if right of ending col
ja chk_inwin_exit
inc al
chk_inwin_exit:
pop cx
pop bx
ret
chk_inwin endp
;-----------------------------------------------------------------------------
; FIND MIN Computes the smaller of two screen coordinates.
; Entry: AX - Row, Column of 1st coordinate
; BX - Pointer to 2nd coordinate
; Exit: AX - Result coordinate.
;-----------------------------------------------------------------------------
find_min proc near
cmp al,[bx]
jbe find_min_1
mov al,[bx]
find_min_1:
cmp ah,[bx+1]
jbe find_min_2
mov ah,[bx+1]
find_min_2:
ret
find_min endp
;-----------------------------------------------------------------------------
; FIND MAX Computes the larger of two screen coordinates.
; Entry: DX - Row, Column of 1st coordinate
; BX - Pointer to 2nd coordinate
; Exit: AX - Result coordinate.
;-----------------------------------------------------------------------------
find_max proc near
cmp dl,[bx]
jae find_max_1
mov dl,[bx]
find_max_1:
cmp dh,[bx+1]
jae find_max_2
mov dh,[bx+1]
find_max_2:
ret
find_max endp
;-----------------------------------------------------------------------------
; COMPUTE BOX Puts the starting row/column in DX and the SI and CX
; Entry: BX - Pointer to coordinates
; Exit: AX - Ending row/column
; DX - Starting row/column
;-----------------------------------------------------------------------------
compute_box proc near
mov ax,[bx]
mov dx,[bx+2]
cmp al,dl
ja compute_box_1
xchg al,dl
compute_box_1:
cmp ah,dh
ja compute_box_2
xchg ah,dh
compute_box_2:
ret
compute_box endp
;-----------------------------------------------------------------------------
; SHOWHELP Displays a help screen on the first three lines of the display
;-----------------------------------------------------------------------------
showhelp proc near
cmp byte ptr no_help,0 ;See if help msg disabled.
jne showhelp_exit
mov dh,1 ;Box at top of screen
mov cx,5
mov di,helpbox_buff
showhelp_1:
push cx
call saveline
inc dh
pop cx
loop showhelp_1
mov dh,1
mov si,offset helpmsg1 ;Write help text line
call writeline
inc dh ;Move to next line
mov si,offset helpmsg2
call writeline
inc dh ;Move to next line
mov si,offset helpmsg3
call writeline
inc dh ;Move to next line
mov si,offset helpmsg4
call writeline
inc dh ;Move to next line
mov si,offset helpmsg5
call writeline
call getkey ;Wait for a key
mov dh,1 ;Box at top of screen
mov cx,5
mov si,helpbox_buff
showhelp_2:
push cx
call restoreline
inc dh
pop cx
loop showhelp_2
showhelp_exit:
ret
showhelp endp
;-----------------------------------------------------------------------------
; MSGBOX displays a message in a text window on the top line of the
; screen. The current data on the screen is saved.
;-----------------------------------------------------------------------------
msgbox proc near
mov dh,0 ;Box at top of screen
mov al,boxactive
cmp al,2 ;Display sum only
je msgbox_1
or al,al ;If box already displayed,
jne msgbox_1 ; don't save screen data.
mov di,MSGBOX_BUFFER
call saveline
msgbox_1:
mov si,offset program1
mov cx,offset program2 - offset program1
xor dx,dx
msgbox_11:
lodsb
call writechar
loop msgbox_11
xor cx,cx
mov cl,screen_cx
sub cl,offset helptag_end - offset helptag
ja msgbox_2
mov cl,screen_cx
inc ch
msgbox_2:
push dx
msgbox_3:
mov al,' ' ;Pad line with spaces
call writechar
cmp dl,cl
jb msgbox_3
or ch,ch
jne msgbox_5
msgbox_4:
mov si,offset helptag
call writestr
msgbox_5:
pop dx
mov boxactive,1 ;Set box active flag
ret
msgbox endp
;-----------------------------------------------------------------------------
; CLEARBOX removes the title box from the screen.
;-----------------------------------------------------------------------------
clearbox proc near
cmp boxactive,0 ;If box already displayed,
je clearbox_2 ; don't save screen data.
mov si,MSGBOX_BUFFER
mov dh,0 ;Box at top of screen
call restoreline
mov boxactive,0 ;Clear box displayed flag
clearbox_2:
ret
clearbox endp
;-----------------------------------------------------------------------------
; WRITELINE Writes a line of help text to the screen. The line is padded
; with spaces to the right.
; Entry: DH - Line on screen to write
; SI - Pointer to ASCIIZ text
;-----------------------------------------------------------------------------
writeline proc near
push dx
xor dl,dl ;Start at left side of screen
call writestr ;Write string
writeline_2:
mov al,' ' ;Pad line with spaces
call writechar
cmp dl,screen_cx
jb writeline_2
pop dx
ret
writeline endp
;-----------------------------------------------------------------------------
; SAVELINE Saves the contents of a screen line ot a buffer
; Entry: DH - Line on screen to save
; DI - Pointer to save buffer
;-----------------------------------------------------------------------------
saveline proc near
push dx
xor dl,dl ;Start at left side of screen
xor cx,cx
mov cl,screen_cx
saveline_1:
call getchar ;Read character from screen
stosw
inc dl ;Point to next character
loop saveline_1
pop dx
ret
saveline endp
;-----------------------------------------------------------------------------
; RESTORELINE Restores the screen that was covered by a line of program
; helptext.
; Entry: DH - Line on screen to restore
; SI - Pointer to buffer that contains original screen contents
;-----------------------------------------------------------------------------
restoreline proc near
push dx
xor dl,dl ;Start at left side of screen
xor cx,cx
mov cl,screen_cx
restoreline_1:
lodsw
call writechar1 ;Read character from screen
loop restoreline_1
pop dx
ret
restoreline endp
;-----------------------------------------------------------------------------
; WRITESTR Writes a string to the screen.
; Entry: DH,DL - Row/Column to write the string
; SI - Pointer to ASCIIZ text
;-----------------------------------------------------------------------------
writestr proc near
mov ah,text_attr
writestr1:
lodsb ;Read text from string, then
or al,al ; call putchar to write to
je writestr_1 ; the screen.
call writechar1
jmp short writestr1
writestr_1:
ret
writestr endp
;-----------------------------------------------------------------------------
; WRITECHAR Writes a character to the screen
; Entry: AL - Character
; DX - Row, Column
;-----------------------------------------------------------------------------
writechar proc near
mov ah,text_attr
writechar1:
call putchar
inc dl
ret
writechar endp
;-----------------------------------------------------------------------------
; GETCHAR Reads a character and its attribute from the screen
; Entry: DH - Row of character to read
; DL - Column of character to read
; Exit: AL - Character
; AH - Attribute
;-----------------------------------------------------------------------------
getchar proc near
push bx
cmp BIOSFlag,0
jne getchar_bios
push cx
push si
push ds
call compute_offset ;Get offset into buffer
shl cx,1 ;Double for char and attr
lds si,video_ptr ;Get ptr to video memory
add si,cx ;Double since char and attr
lodsw ;Read char/attribute
pop ds
pop si
pop cx
jmp short getchar_exit
getchar_bios:
mov ah,2 ;Set cursor
mov bh,screen_page
int 10h
mov ah,8 ;Read character/attr
int 10h
getchar_exit:
pop bx
ret
getchar endp
;-----------------------------------------------------------------------------
; PUTCHAR Writes a character and its attribute to the screen
; Entry: AL - Character to write
; AH - Attribute to write
; DH - Row of character to write
; DL - Column of character to write
;-----------------------------------------------------------------------------
putchar proc near
push bx
push cx
push ax
cmp BIOSFlag,0
jne putchar_bios
push di
push es
call compute_offset ;Get offset into buffer
shl cx,1 ;Double since char and attr
les di,video_ptr
add di,cx ;Add to start of buffer
stosw ;Read char/attribute
pop es
pop di
jmp short putchar_exit
putchar_bios:
mov ah,2 ;Set cursor
mov bh,screen_page
int 10h
pop ax
push ax
mov bl,ah ;Copy attribute
mov ah,9 ;Read character/attr
mov cx,1
int 10h
putchar_exit:
pop ax
pop cx
pop bx
ret
putchar endp
;-----------------------------------------------------------------------------
; GETKEY Waits for a key from the keyboard.
; Exit: AX - Scan code, ASCII char from keyboard.
;-----------------------------------------------------------------------------
getkey proc near
mov ah,1 ;Check for key
int 16h
jnz getkey_exit
int 28h ;Call DOS Idle
mov ax,1680h ;Release Timeslice
int 2fh
jmp short getkey
getkey_exit:
xor ax,ax ;Get key
int 16h
ret
getkey endp
align 16
end_of_resident = $
;----------------------------------------------------------------------------
; Non-resident data.
;----------------------------------------------------------------------------
alrdy_installed db 0 ;Installed flag
installed_seg dw 0 ;Segment of installed code
dos_version dw 0 ;DOS version
infomsg2 db "DOSCLIP uninstalled$"
errmsg0 db "Need DOS 3.0 or greater$"
errmsg1 db "DOSCLIP not installed$"
errmsg2 db "Usage: DOSCLIP [/B][/U]",13,10
db "/B = Use Video BIOS",13,10
db "/U = Uninstall",13,10,"$"
errmsg3 db "Can",39,"t uninstall$"
errmsg4 db "DOSCLIP already installed$"
errmsg5 db "Can not find Critical error flag$"
endmsg db 13,10,"$"
infomsg1 db "DOSCLIP installed",13,10,10
db "Copy key is "
db "Alt C",13,10
db "Paste key is "
db "Alt V","$"
;----------------------------------------------------------------------------
; Initialization routine.
;----------------------------------------------------------------------------
initialize proc near
assume cs:code,ds:code,es:code
cld
mov dx,offset program ;Print copyright message
call printmsgcr
mov ah,30h ;Get DOS version
int 21h
xchg al,ah ;Swap major, minor numbers
mov dx,offset errmsg0 ;Bad DOS version
cmp ah,3 ;Run if DOS 3.0 or greater.
jb disp_error
mov dos_version,ax ;Save version number
mov ax,offset end_of_code+512 ;Set stack ptr
mov sp,ax
add ax,15
mov cl,4 ;Convert offset to segment size
shr ax,cl
mov ah,4ah ;Reduce memory allocation
int 21h
call find_installed ;See if already installed
jc init_1
inc alrdy_installed ;Yes, set flag
mov installed_seg,es ;Save seg of installed code
init_1:
push ds
pop es
mov dx,offset errmsg4 ;Default message
mov di,80h ;Parse command line
xor cx,cx
or cl,[di] ;Get length of cmd line
je init_exit
init_2:
mov al,'/'
repne scasb ;Find command line switches
jne init_exit
mov al,[di] ;Get comamnd line switch
or al,20h
cmp al,'b' ;See if Video BIOS parameter
jne init_3
inc BIOSFlag
jmp short init_2
init_3:
cmp al,'u' ;See if uninstall
je init_4
mov dx,offset errmsg2 ;Print useage statement
;
;Display error message.
;
assume ds:nothing
disp_error:
push cs
pop ds
assume ds:code
call printmsgcr ;print string
mov ax,4c01h ;Terminate with RC = 1
int 21h
init_4:
call remove ;Remove installed copy
jc disp_error
jmp short exit
init_exit:
cmp alrdy_installed,0
jne disp_error
call install
jc disp_error
exit:
mov ax,4C00h ;Terminate with RC = 0
int 21h
initialize endp
;-----------------------------------------------------------------------------
; INSTALL Installs the program
;-----------------------------------------------------------------------------
assume cs:code,ds:code,es:code
install proc near
mov ah,34h ;Get ptr to INDOS flag
int 21h
mov word ptr indos_ptr,bx
mov word ptr indos_ptr[2],es
call findCEF ;Get ptr to crit error flag
jnc install_1
jmp install_error
install_1:
;
;Set interrupt vectors
;
mov word ptr criterr_ptr,bx
mov word ptr criterr_ptr[2],es
mov al,08h ;Get/set the timer interrupt
mov dx,offset timerint
mov di,offset int08h
call set_interrupt
mov al,09h ;Get/set the keyboard int
mov dx,offset keyint
mov di,offset int09h
call set_interrupt
mov al,10h ;Get/set the video interrupt
mov dx,offset videoint
mov di,offset int10h
call set_interrupt
mov al,13h ;Get/set the disk interrupt
mov dx,offset diskint
mov di,offset int13h
call set_interrupt
mov al,28h ;Get/set the DOS idle int
mov dx,offset idleint
mov di,offset int28h
call set_interrupt
mov al,2Fh ;Get/set the DOS Multiplex
mov dx,offset muxint
mov di,offset int2Fh
call set_interrupt
push cs
push cs
pop ds
assume ds:code
pop es
assume es:code
mov dx,offset infomsg1 ;Print program installed msg
call printmsgcr
;
;Init buffer pointers.
;
mov dx,ATTR_BUFFER ;Set pointers for resident
add dx,attr_buffsize ; code.
mov helpbox_buff,dx
add dx,HELPBOX_BUFFSIZE
;
;Init clipboard pointers.
;
mov word ptr [clipboard_buff],dx
mov bx,dx ;Save size of save data area
add dx,clipboard_size ;Add size of clipboard
mov ax,cs
mov word ptr [clipboard_buff+2],ax
mov word ptr [clipboard_dptr+2],ax
mov word ptr [clipboard_dsize],0
mov paste_flag,0
;
;Init switcher structures
;
mov word ptr [DataBlockPtr+2],ax
mov word ptr [DataBlockPtr],offset DataBlock
mov word ptr [DataBlockSize],INSTDATASIZE
mov word ptr [StackBlockPtr+2],ax
mov word ptr [StackBlockPtr],offset end_of_resident
sub bx,offset end_of_resident ;Compute size of
mov word ptr [StackBlockSize],bx ; Data save area
mov word ptr [sisInstData+2],ax
mov ax,offset DataBlockPtr
mov word ptr [sisInstData],ax
push dx ;Save Ptr to end of resident
mov ax,1600h ;See if Enhanced mode windows
int 2fh
or al,al
je nowin
inc win_enhanced ;Set enhanced mode flag
nowin:
pop dx ;Get Ptr to end of resident
add dx,15
mov cl,4
shr dx,cl
mov ax,3100h ;Terminate and stay resident
int 21h
install_error:
ret
install endp
;-----------------------------------------------------------------------------
; REMOVE uninstalls the installed program from memory.
;-----------------------------------------------------------------------------
remove proc near
assume ds:code,es:code
push ds
push es
mov ds,installed_seg ;Point DS to installed code
assume ds:nothing
mov dx,offset errmsg1 ;Not installed message
cmp alrdy_installed,0
je remove_error1
mov al,8 ;Restore int 8 (Timer)
mov dx,offset timerint
mov di,offset int08h
call restore_int
jc remove_error
mov al,9 ;Restore int 9 (keyboard)
mov dx,offset keyint
mov di,offset int09h
call restore_int
jc remove_error
mov al,10h ;Restore int 10h (BIOS Video)
mov dx,offset videoint
mov di,offset int10h
call restore_int
jc remove_error
mov al,13h ;Restore int 13h (BIOS disk)
mov dx,offset diskint
mov di,offset int13h
call restore_int
jc remove_error
mov al,28h ;Restore int 28h (DOS Idle)
mov dx,offset idleint
mov di,offset int28h
call restore_int
jc remove_error
mov al,2Fh ;Restore int 2Fh (DOS Mux)
mov dx,offset muxint
mov di,offset int2Fh
call restore_int
jc remove_error
mov es,ds:[2ch] ;Get installed env seg
mov ah,49h
int 21h ;Free installed env segment
push ds
pop es
mov ah,49h ;Free installed program segment
int 21h
mov ax,cs
mov ds,ax
mov es,ax
mov dx,offset infomsg2 ;Print program removed msg
call printmsgcr
clc
remove_exit:
pop ds
pop es
ret
remove_error:
mov dx,offset errmsg3 ;Can't uninstall msg
remove_error1:
stc
jmp short remove_exit
remove endp
;-----------------------------------------------------------------------------
; SETINTERRUPT Get and sets an interrupt
; Entry: AL - Interrupt number
; DX - Pointer to new interrupt routine
; DI - Pointer to storage location for old interrupt vector
;-----------------------------------------------------------------------------
assume cs:code,ds:code,es:nothing
set_interrupt proc near
push es
push ax
mov ah,35h ;DOS get interrupt
int 21h
pop ax
mov word ptr [di],bx ;Save old vector
mov word ptr [di+2],es
mov ah,25h ;DOS set interrupt
int 21h
pop es
ret
set_interrupt endp
;-----------------------------------------------------------------------------
; RESTOREINT Checks to see if an interrupt vector has been changed, if not
; the interrupt vector is restored with its original value
; Entry: AL - Interrupt number
; DS:DX - Pointer to current interrupt routine
; DS:DI - Pointer to old interrupt vector
;-----------------------------------------------------------------------------
assume cs:code,ds:nothing
restore_int proc near
push es
push ax
mov ah,35h ;DOS get interrupt
int 21h
pop ax ;Get back interrupt number
cmp dx,bx ;Compare routine offset
jne restoreint_error
mov bx,es ;Get current vector segment
mov cx,ds ;Get installed segment
cmp cx,bx ;Compare routine segment
jne restoreint_error
push ds
lds dx,ds:[di] ;Get old vector
mov ah,25h ;DOS set interrupt
int 21h
clc
pop ds
restoreint_exit:
pop es
ret
restoreint_error:
stc
jmp short restoreint_exit
restore_int endp
;-----------------------------------------------------------------------------
; FINDCEF Finds the DOS ErrorMode (Critical error) flag
; Exit: ES:BX - Segment,offset of ErrorMode flag
; CF - Clear if flag found
;-----------------------------------------------------------------------------
findCEF proc near
mov ah,34h ;Get InDOS address
int 21h
dec bx
cmp dos_version,30ah ;If DOS 3.1 or later, ErrorMode
jnc findCEF_exit ; sits before InDOS.
mov ax,3e80h ;CMP opcode
mov si,028cdh ;Int 28 Opcode
mov dl,75h ;JNE Opcode
mov cx,-1 ;max search length
mov di,bx ;start at INDOS address
findCEF_1:
repne scasb ;do the search
jcxz findCEF_notfound ;branch if search failed
cmp es:[di],ah ;Check other half of CMP opcode
jne findCEF_1
cmp byte ptr es:[di+4],dl ;Check for JNE
jne findCEF_1
cmp word ptr es:[di+6],si ; Check for Int 28h call
jne findCEF_1 ;Resume loop if not found
inc di
mov bx,es:[di] ;Get offset of ErrorMode flag
clc
findCEF_exit:
ret
findCEF_notfound:
stc
mov dx,offset errmsg5 ;Can't find Critical Error flg
jmp short findCEF_exit
findCEF endp
;-----------------------------------------------------------------------------
; FIND INSTALLED Find the installed code by scanning the memory control blocks.
; Exit: AX - Segment of installed code if found.
; CF - Clear if installed code found
;-----------------------------------------------------------------------------
find_installed proc near
assume ds:code,es:code
mov word ptr prog,0
mov bx,0A000h ;Start at upper mem blk start
mov ax,cs ;keep CS value in AX
find_installed_1:
inc bx ;increment search segment value
mov es,bx
assume es:nothing
cmp ax,bx ;not installed if current
je find_installed_2 ; segment is found.
call cmpheader
jne find_installed_1 ;loop back if not found
clc
find_installed_exit:
ret
find_installed_2:
stc
jmp short find_installed_exit
find_installed endp
;-----------------------------------------------------------------------------
; CMPHEADER compares the first 16 bytes of this file with the segment
; pointed to by ES.
; Entry: DS - code segment
; ES - pointer to segment to compare
; Exit: ZF - 0 = segments match.
;-----------------------------------------------------------------------------
cmpheader proc near
assume ds:code,es:nothing
mov si,offset prog ;Search this segment for ASCII
mov di,si ; fingerprint.
mov cx,16
repe cmpsb
ret
cmpheader endp
;-----------------------------------------------------------------------------
; PRINTMSG prints the message pointed to by DX to the screen.
; Entry: DX - pointer to ASCII message terminated by $
;-----------------------------------------------------------------------------
printmsg proc near
assume ds:nothing,es:nothing
push ds
push cs
pop ds
assume ds:code
mov ah,9 ;Print message
int 21h
pop ds
ret
printmsg endp
;-----------------------------------------------------------------------------
; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the message.
; Entry: DX - pointer to ASCII message terminated by $
;-----------------------------------------------------------------------------
printmsgcr proc near
assume ds:nothing,es:nothing
push dx
call printmsg
mov dx,offset endmsg
call printmsg
pop dx
ret
printmsgcr endp
even
end_of_code = $
code ends
end prog